package com.htudata.transctAlarm.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.htudata.alarm.pojo.po.AlarmLevelPO;
import com.htudata.common.enums.RequestSeqEnum;
import com.htudata.common.service.DataEhcacheService;
import com.htudata.common.vo.ResponseResult;
import com.htudata.core.util.ResultGenerator;
import com.htudata.core.util.operation.CollectionsOperationUtils;
import com.htudata.core.util.operation.DateTimeOperationUtils;
import com.htudata.core.util.operation.FastJsonOperationUtils;
import com.htudata.core.util.operation.MapOperationUtils;
import com.htudata.item.service.ItemSelectService;
import com.htudata.transctAlarm.dao.TransctAlarmDao;
import com.htudata.transctNode.service.impl.TransctNodeShowService;
import com.htudata.user.dao.UserDao;
import com.htudata.websocket.endpoint.AgentServerEndpoint;
import com.htudata.zabbix.problem.service.ProblemService;
import com.htudata.zabbix.trigger.service.ZBXTriggerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TransctAlarmShowService {

  @Autowired
  private ProblemService problemService;
  
  @Autowired
  private TransctAlarmLevelService alarmLevelService;
  
  @Autowired
  private ZBXTriggerService zbxTriggerService;
  
  @Autowired
  private ItemSelectService itemSelectService;
  
  @Autowired
  private DataEhcacheService dataEhcacheService;
  
  @Autowired
  private TransctAlarmShowService alarmShowService;
  
  @Autowired
  private TransctNodeShowService nodeShowService;
  
  @Autowired
  private AgentServerEndpoint agentServerEndpoint;
  
  @Autowired
  private TransctAlarmDao alarmDao;
  
  @Autowired
  private UserDao userDao;
  
  public JSONArray getNodeProblemCountByFlowId(String flowId, int recoverTime) {
    return this.alarmDao.selectNodeProblemCountByFlowId(flowId, recoverTime);
  }
  
  public JSONArray getNodeAlarmCountByFlowId(String flowId, int recoverTime, long userId) {
    return this.alarmDao.selectNodeAlarmCountByFlowId(flowId, recoverTime, userId);
  }
  
  public JSONArray getNodeProblemCountByVirtualStation(int recoverTime, int nodeTypeId, String nodeId, String areaCode) {
    return this.alarmDao.selectNodeProblemCountByVirtualStation(recoverTime, nodeTypeId, nodeId, areaCode);
  }
  
  public JSONArray getNodeAlarmCountByVirtualStation(int recoverTime, int nodeTypeId, String nodeId, String areaCode) {
    return this.alarmDao.selectNodeAlarmCountByVirtualStation(recoverTime, nodeTypeId, nodeId, areaCode);
  }
  
  public JSONArray getNodeProblemCountByLevel(int recoverTime, int nodeTypeId, String nodeId, String areaCode, int level) {
    return this.alarmDao.selectNodeProblemCountByLevel(recoverTime, nodeTypeId, nodeId, areaCode, level);
  }
  
  public JSONArray getNodeAlarmCountByLevel(int recoverTime, int nodeTypeId, String nodeId, String areaCode, int level) {
    return this.alarmDao.selectNodeAlarmCountByLevel(recoverTime, nodeTypeId, nodeId, areaCode, level);
  }
  
  public void sendAlarms() throws Exception {
    try {
      Map<String, List<Long>> currentUserIds = this.agentServerEndpoint.getCurrentUserIds();
      if (!MapOperationUtils.isValidMap(currentUserIds))
        return; 
      JSONArray mngUserIds = this.userDao.selectUserIdsByRoleType(1L);
      JSONObject mngUserIdJO = FastJsonOperationUtils.JSONArrayToJSONObejct(mngUserIds, "userId", false);
      Map<String, String> alarmMap = new HashMap<>();
      List<Long> userIds = null;
      for (Map.Entry<String, List<Long>> entry : currentUserIds.entrySet()) {
        userIds = (List<Long>)((List)entry.getValue()).stream().distinct().collect(Collectors.toList());
        Map<Long, Map<String, String>> userIdsAndNodeIds = this.nodeShowService.getUserIdsAndNodeIds(userIds);
        JSONObject alarmsOrigin = (JSONObject)JSON.toJSON(this.alarmShowService.getAlarms(true, ""));
        Map<String, String> nodeIdMap = null;
        for (Iterator<Long> iterator = userIds.iterator(); iterator.hasNext(); ) {
          long userId = ((Long)iterator.next()).longValue();
          JSONObject alarmsTemp = (JSONObject)alarmsOrigin.clone();
          if (mngUserIdJO.containsKey(userId + "")) {
            alarmMap.put(userId + "", alarmsTemp.toJSONString());
            continue;
          } 
          nodeIdMap = userIdsAndNodeIds.get(Long.valueOf(userId));
          JSONArray alarms = alarmsTemp.getJSONArray("data");
          JSONArray alarmsNew = new JSONArray();
          for (int i = 0, length = alarms.size(); i < length; i++) {
            JSONObject alarm = (JSONObject)alarms.get(i);
            if (MapOperationUtils.isValidMap(nodeIdMap))
              if (nodeIdMap.containsKey(alarm.getString("nodeId"))) {
                alarmsNew.add(alarm);
              } else if (nodeIdMap.containsKey(alarm.getString("parentNodeId"))) {
                alarmsNew.add(alarm);
              }  
          } 
          alarmsTemp.put("data", alarmsNew);
          alarmMap.put(userId + "", alarmsTemp.toJSONString());
        } 
      } 
      this.agentServerEndpoint.sendToALLUser(alarmMap);
    } catch (Exception e) {
       throw e;
    } 
  }
  
  public ResponseResult getAlarms(boolean needJudgeChange, String a2) throws Exception {
    ResponseResult responseResult = null;
    try {
      responseResult = ResultGenerator.genResult(RequestSeqEnum.SEQ_003.getCode(), getAlarmList(a2));
    } catch (Exception e) {
      throw e;
    } 
    return responseResult;
  }
  
  public List<Object> getAlarmList(String a2) throws Exception{
    List<Object> result = new ArrayList();
    try {
      JSONArray effectiveLocalAlarms = getEffectiveLocalAlarms();
      if (CollectionsOperationUtils.isValidCollection((Collection)effectiveLocalAlarms))
        result.addAll((Collection<?>)effectiveLocalAlarms); 
    } catch (Exception e) {
      throw e;
    } 
    return result;
  }
  
  private List<Object> problemsToAlarms(JSONArray problems, String a2) throws Exception {
    JSONObject problem = null;
    JSONArray triggerIds = new JSONArray();
    for (Object obj : problems) {
      problem = (JSONObject)obj;
      if (!ProblemService.isTriggerProblem(problem.getIntValue("source"), problem.getIntValue("object")))
        continue; 
      triggerIds.add(Long.valueOf(problem.getLongValue("objectid")));
    } 
    if (!CollectionsOperationUtils.isValidCollection((Collection)triggerIds))
      return Collections.EMPTY_LIST; 
    JSONObject zbxTriggerIdsAndItemId = this.zbxTriggerService.getZBXTriggerIdsAndItemId((List)triggerIds, -1);
    if (zbxTriggerIdsAndItemId == null)
      return Collections.EMPTY_LIST; 
    JSONArray itemIds = new JSONArray();
    for (Map.Entry<String, Object> entry : (Iterable<Map.Entry<String, Object>>)zbxTriggerIdsAndItemId.entrySet())
      itemIds.addAll((Collection)((JSONObject)entry.getValue()).getJSONArray("items")); 
    if (!CollectionsOperationUtils.isValidCollection((Collection)itemIds))
      return Collections.EMPTY_LIST; 
    JSONArray nodeAndFlowJSONArray = this.itemSelectService.getNodeAndFlowByItemId((List)itemIds);
    if (!CollectionsOperationUtils.isValidCollection((Collection)nodeAndFlowJSONArray))
      return Collections.EMPTY_LIST; 
    JSONObject nodeAndFlowJSONObject = FastJsonOperationUtils.JSONArrayToJSONObejct(nodeAndFlowJSONArray, "item_id", false);
    if (!MapOperationUtils.isValidMap((Map)nodeAndFlowJSONObject))
      return Collections.EMPTY_LIST; 
    return problemsToAlarms2(problems, this.alarmLevelService.getAlarmLevelList(a2), zbxTriggerIdsAndItemId, nodeAndFlowJSONObject);
  }
  
  private List<Object> problemsToAlarms2(JSONArray problems, List<AlarmLevelPO> alarmLevelList, JSONObject zbxTriggerIdsAndItemId, JSONObject nodeAndFlowJSONObject) {
    JSONArray result = new JSONArray();
    JSONObject problem = null;
    String triggerId = "";
    JSONObject zbxTriggerIdAndItemId = null;
    String itemId = "";
    JSONObject nodeAndFlow = null;
    AlarmLevelPO alarmLevelPO = null;
    for (Object obj : problems) {
      problem = (JSONObject)obj;
      if (problem.getIntValue("r_clock") != 0)
        continue; 
      if (!ProblemService.isTriggerProblem(problem.getIntValue("source"), problem.getIntValue("object")))
        continue; 
      triggerId = problem.getString("objectid");
      zbxTriggerIdAndItemId = (JSONObject)zbxTriggerIdsAndItemId.get(triggerId);
      if (zbxTriggerIdAndItemId == null)
        continue; 
      itemId = ((JSONObject)zbxTriggerIdAndItemId.getJSONArray("items").get(0)).getString("itemid");
      nodeAndFlow = (JSONObject)nodeAndFlowJSONObject.get(itemId);
      if (nodeAndFlow == null)
        continue; 
      alarmLevelPO = TransctAlarmLevelService.getAlarmLevelInfo(alarmLevelList, problem.getIntValue("severity"));
      result.add(problemToAlarm(problem, alarmLevelPO, nodeAndFlow));
    } 
    return (List<Object>)result;
  }
  
  private JSONObject problemToAlarm(JSONObject problem, AlarmLevelPO alarmLevelPO, JSONObject nodeAndFlow) {
    JSONObject result = new JSONObject(true);
    result.put("alarmId", Long.valueOf(problem.getLongValue("eventid")));
    result.put("triggerId", Long.valueOf(problem.getLongValue("objectid")));
    result.put("problem", problem.getString("name"));
    result.put("status", Integer.valueOf(problem.getIntValue("acknowledged")));
    result.put("startTime", DateTimeOperationUtils.format(new Date(problem.getIntValue("clock") * 1000L), "yyyyMMdd HH:mm:ss"));
    int recoveryTime = problem.getIntValue("r_clock");
    if (recoveryTime != 0) {
      long timeStampShift = (recoveryTime - problem.getIntValue("clock"));
      result.put("duration", DateTimeOperationUtils.timeStampToStringNew(timeStampShift, 3));
    } else {
      int currentTimestamp = (int)(System.currentTimeMillis() / 1000L);
      long timeStampShift = (currentTimestamp - problem.getIntValue("clock"));
      result.put("duration", DateTimeOperationUtils.timeStampToStringNew(timeStampShift, 3));
    } 
    if (alarmLevelPO != null) {
      result.put("level", Integer.valueOf(alarmLevelPO.getLevel()));
      result.put("color", alarmLevelPO.getColor());
    } else {
      result.put("level", Integer.valueOf(problem.getIntValue("severity")));
      result.put("color", "#ffffff");
    } 
    result.put("flowId", nodeAndFlow.getString("flowId"));
    result.put("flowName", nodeAndFlow.getString("flowName"));
    result.put("nodeId", nodeAndFlow.getString("node_id"));
    result.put("hostName", nodeAndFlow.getString("hostName"));
    result.put("type", Integer.valueOf(0));
    return result;
  }
  
  public JSONArray getEffectiveLocalAlarms() throws Exception {
    JSONArray effectiveLocalAlarms = this.alarmDao.selectEffectiveLocalAlarms();
    int currentTimestamp = (int)(System.currentTimeMillis() / 1000L);
    List<AlarmLevelPO> alarmLevelList = this.alarmLevelService.getAlarmLevelList(null);
    effectiveLocalAlarms.forEach(effectiveLocalAlarm -> {
        try {
          JSONObject effectiveLocalAlarmObject = (JSONObject)effectiveLocalAlarm;
          Date startTime  = DateTimeOperationUtils.parse(String.valueOf(effectiveLocalAlarmObject.getLongValue("startTime")), "yyyyMMddHHmmss");
          long timeStampShift = currentTimestamp - startTime.getTime() / 1000L;
          effectiveLocalAlarmObject.put("duration", DateTimeOperationUtils.timeStampToStringNew(timeStampShift, 3));
          effectiveLocalAlarmObject.put("startTime", DateTimeOperationUtils.format(startTime, "yyyyMMdd HH:mm:ss"));
          AlarmLevelPO alarmLevelPO = TransctAlarmLevelService.getAlarmLevelInfo(alarmLevelList, effectiveLocalAlarmObject.getIntValue("level"));
          effectiveLocalAlarmObject.put("color", alarmLevelPO.getColor());
          effectiveLocalAlarmObject.put("type", Integer.valueOf(1));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    });
    return effectiveLocalAlarms;
  }
}
